feat: expose the identification source in mx::api - #419
Merged
webern merged 3 commits intoAug 23, 2026
Conversation
MusicXML lets a <note> carry its own playback velocity in the dynamics and end-dynamics attributes, the MIDI Note On and Note Off velocities expressed as percentages of the default forte level. The api had no home for either, so the reader dropped them and an author could not state them. NoteData gains velocityStart and velocityStop. Both are optional doubles that default to empty, so a note that says nothing about playback still writes no attribute. The names avoid "dynamics", which in the api already means the printed marking (a MarkData in noteAttachmentData) rather than how hard the note is played. Pins the thirteen foundsuite Inventions in the api round-trip baseline. Each one carried a per-note velocity that was the only thing it lost on write.
MusicXML's <identification>/<source> names the edition, manuscript, or other publication a score was made from. The api had nowhere to keep it, so the reader discarded it and every write dropped the element. ScoreData gains an optional source string. Optional rather than a plain string because <source></source> is legal and means something different from saying nothing at all. Pins five more files in the api round-trip baseline whose only divergence was the dropped element.
This was referenced Aug 23, 2026
Base automatically changed from
claude/mx-api-roundtrip-corpus-9pkrg6-01-note-velocity
to
main
August 23, 2026 18:49
…ntification-source Signed-off-by: Matthew James Briggs <matthew.james.briggs@gmail.com>
webern
deleted the
claude/mx-api-roundtrip-corpus-9pkrg6-02-identification-source
branch
August 23, 2026 18:51
webern
added a commit
that referenced
this pull request
Aug 23, 2026
## Human Summary Adds support for `directive`. ## Summary `<direction directive="yes">` aligns a direction with the measure's time signature rather than with the note it is anchored to. That is how a tempo or style marking at the head of a movement is usually placed. The api had no field for it, so the reader discarded it and the attribute was dropped on write. `DirectionData` gains `Bool directive`, following the api's tri-state convention: `unspecified` does not write an attribute, `yes` and `no` are written verbatim. `<harmony>` does not carry `directive` even though it shares `placement` and `system` with `<direction>`, so the reader only looks for it on `<direction>`. Non-breaking: one new field defaulting to `unspecified`. ## Round-trip corpus Adds 3 files to `roundtrip-baseline.txt` (399 -> 402). `attr:direction@directive` was the third entry on the classifier worklist. ## Testing - [x] Two new `DirectionWriter` impl tests: the api -> core -> api round trip of `yes`, and that `unspecified` leaves the attribute off entirely (`*directive*`: 9 assertions in 2 test cases) - [x] `make api-test` (6306 assertions in 579 test cases) - [x] `make api-roundtrip` (402 passed, 0 failed of 402 pinned) - [x] `make api-roundtrip-discover` reports exactly the 3 new passes and no regressions - [x] `make fmt` ## References - Progresses the round-trip corpus work tracked in #208 - Stacked on #419, which is stacked on #417. The base branch is #419's branch, so this diff shows only the directive change. --------- Signed-off-by: Matthew James Briggs <matthew.james.briggs@gmail.com>
webern
added a commit
that referenced
this pull request
Aug 26, 2026
## Human Summary Not a functional feature, but we now respect a file that emits `<staves>1</staves>` when we write it back. ## Summary MusicXML states a part's staff count in `<attributes>/<staves>`, and a part that omits the element has one staff. mx wrote the element only when the part had more than one staff, so a source that spelled out the redundant `<staves>1</staves>` lost it. `PartData` gains `bool writeStaffCount`, defaulting to false. It only affects a single-staff part: a part with more than one staff writes its count either way, since without it every note would land on staff one. The reader sets it when the source spelled the element out and the count is one, so the common case stays at the default. `PartReader::calculateNumStaves` now also reports whether a `<staves>` element was seen. The count alone cannot tell you, since one is both "the source said one" and "the source said nothing". Non-breaking: one new field defaulting to the behavior mx had before. ## Round-trip corpus Adds 3 files to `roundtrip-baseline.txt` (402 -> 405). `drop:staves` was the fourth entry on the classifier worklist. ## Testing - [x] New `StaffCountApiTest` covers the single-staff default, the single-staff override, and a two-staff part that writes its count regardless (`*StaffCount*`: 8 assertions in 3 test cases) - [x] `make api-test` (6314 assertions in 582 test cases) - [x] `make api-roundtrip` (405 passed, 0 failed of 405 pinned) - [x] `make api-roundtrip-discover` reports exactly the 3 new passes and no regressions - [x] `make fmt` ## References - Progresses the round-trip corpus work tracked in #208 - Stacked on #420, #419, #417. The base branch is #420's branch, so this diff shows only the staff-count change. --- _Generated by [Claude Code](https://claude.ai/code/session_01RmcR2rHB4dLWjtPWqGrQxV)_ --------- Signed-off-by: Matthew James Briggs <matthew.james.briggs@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Human Summary
Add support to
mx::apifor the<source>element. Seen in some corpus files.Summary
<identification>/<source>names the edition, manuscript, or other publication a score was made from.mx::apihad nowhere to keep it, so the reader discarded it and every write dropped the element.ScoreDatagainsstd::optional<std::string> source, read from and written to<identification>.Optional rather than a plain string like its
copyrightneighbor:<source></source>is legal MusicXML and says the score named a source and left it blank, which is a different fact from saying nothing at all. A plain string would collapse the two.Non-breaking: one new optional field.
Round-trip corpus
Adds 5 files to
roundtrip-baseline.txt(394 -> 399).drop:sourcewas the second entry on the classifier worklist, blocking these five on its own.Testing
IdentificationSourceApiTestcovers the round trip, the written element, the empty default, and the blank-but-present case (*IdentificationSource*: 7 assertions in 4 test cases)make api-test(6297 assertions in 577 test cases)make api-roundtrip(399 passed, 0 failed of 399 pinned)make api-roundtrip-discoverreports exactly the 5 new passes and no regressionsmake fmtReferences